package com.chenjun.web.task;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.chenjun.common.Constant;
import com.chenjun.common.model.DataGridModel;
import com.chenjun.common.model.DataGridSortModel;
import com.chenjun.common.util.DateUtil;
import com.chenjun.core.dao.generator.entity.OaBillAttnDayReport;
import com.chenjun.core.dao.generator.entity.OaBillAttnDetail;
import com.chenjun.core.dao.generator.entity.OaBillAttnMonthReport;
import com.chenjun.core.dao.generator.entity.OaBillAttnMonthReportDtl;
import com.chenjun.core.dao.generator.entity.OaBillLeaveApplication;
import com.chenjun.core.dao.generator.entity.OaBillOvertimeApplication;
import com.chenjun.core.service.oa.LeaveManagerService;
import com.chenjun.core.service.oa.LeaveTypeManagerService;
import com.chenjun.core.service.oa.OaBillAttnDayReportService;
import com.chenjun.core.service.oa.OaBillAttnDetailService;
import com.chenjun.core.service.oa.OaBillAttnMonthReportDtlService;
import com.chenjun.core.service.oa.OaBillAttnMonthReportService;
import com.chenjun.core.service.oa.OvertimeManagerService;

/**
 * 明细结算定时任务
 * @Description: 结算日报、月报
 * @author dongyibin
 * @date 2017-8-19 下午8:33:16
 */
@Component
public class TimeTaskService {
	private Logger logger = Logger.getLogger(getClass());
	@Autowired
	private OaBillAttnDetailService detailService;
	@Autowired
	private OaBillAttnDayReportService dayReportService;
	@Autowired
	private OaBillAttnMonthReportService monthReportService;
	@Autowired
	private OaBillAttnMonthReportDtlService monthReportDtlService;
	@Autowired
	private LeaveManagerService leaveManagerService;
	@Autowired
	private LeaveTypeManagerService leaveTypeManagerService;
	@Autowired
	private OvertimeManagerService overtimeManagerService;
	
	
	/**
	 * @Description: 添加考勤明细  
	 * @author dongyibin
	 * @date 2017-8-19 下午8:58:00
	 */
	// @Scheduled(cron="0/5 * *  * * ?")
	/*public void addAttendanceDetail(){
		for(int i=0; i<5; i++){
			OaBillAttnDetail oa = new OaBillAttnDetail();
			oa.setNo("123456" + i);
			oa.setBillDate(DateUtil.parseShotStringToDate("2017-08-26"));
			oa.setEmplId("suerid" + i);
			oa.setEmplCode("123456" + i);
			oa.setManHoursTypeId(1);
			oa.setManHoursTypeName("标准工时制");
			oa.setClockTime(DateUtil.parseStringToDate("2017-08-26 18:02:00"));
			oa.setClockPlace("无锡");
			oa.setClockIp("127.0.0.1");
			oa.setAttnTypeId(2);
			oa.setAttnTypeName("手机考勤(GPS定位)");
			
			oaBillAttnDetailService.create(oa);
		}
		System.out.print(System.currentTimeMillis());
		System.out.println("===================定时器启用成功====================");
	}*/
	
	/**
	 * @Description: 日结表统计
	 * @author dongyibin
	 * @date 2017-8-19 下午8:35:44
	 */
	@Scheduled(cron="0 30 1 * * ?") // 每天1点30分执行
	public void dailyReport(){
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DAY_OF_MONTH, -1); // 取前一天数据
		Date billDate = calendar.getTime(); // 日报数据日期
		String beforeTime = DateUtil.dateToStrShort(billDate);
		DataGridModel param = new DataGridModel();
		param.setRows(0);
		param.getParams().put("clockTime", beforeTime + " 00:00:00");
		// 得到这天所有打卡员工ID
		List<OaBillAttnDetail> distinctByEmplid = detailService.getDistinctByEmplid(param);
		for(OaBillAttnDetail oaBillAttnDetail : distinctByEmplid){
			String emplid = oaBillAttnDetail.getEmplId(); 
			if(StringUtils.isBlank(emplid)){
				continue;
			}
			param = new DataGridModel();
			param.setRows(0);
			param.getParams().put("emplId", emplid);
			param.getParams().put("startClockTime", beforeTime + " 00:00:00");
			param.getParams().put("endClockTime", beforeTime + " 23:59:59");
			param.getSortBy().add(new DataGridSortModel("clock_time", DataGridSortModel.ASC));
			// 取得用户当天打卡记录
			List<OaBillAttnDetail> userClockRecords = detailService.doListByCondition(param);
			if (!(userClockRecords == null || userClockRecords.isEmpty())) { // 没取到数据
				int size = userClockRecords.size();
				OaBillAttnDayReport dayReport = new OaBillAttnDayReport();
				float normalHours = 0f;  // 打卡记录少于两次,工作时间为0小时
				float overtimeHours = 0f; // 仅标准工时制有加班时间
				if (size > 1) { // 两次以上打卡数据
					// 取一头一尾
					OaBillAttnDetail startDetail = userClockRecords.get(0);
					OaBillAttnDetail endDetail = userClockRecords.get(size - 1);
					int hoursTypeid = startDetail.getManHoursTypeId(); // 工时制ID
					Date firstClockDate = startDetail.getClockTime();// 第一次打卡时间
					Date lastClockDate = endDetail.getClockTime(); // 最后打卡时间
					// long clockTime = lastClockDate.getTime() - firstClockDate.getTime(); // 员工最大打卡间隔时间
					// 员工第一次打卡时间
					long firstClockTime = DateUtil.strDateToShortTime(DateUtil.dateToShortTime(firstClockDate)).getTime();
					// 员工最后一次打卡时间
					long lastClockTime = DateUtil.strDateToShortTime(DateUtil.dateToShortTime(lastClockDate)).getTime();
					if(hoursTypeid == Constant.STANDARD_HOURS_TYPE){ // 标准工时制
						// 按公司设置标准时间来
						// long oneHours = 1 * 60 * 60 * 1000;
						// long standardTime = 8 * oneHours; // 标准时间8小时
						// 还要与公司设定的上班时间比较
						long companyStartTime = DateUtil.strDateToShortTime("08:30").getTime(); // 公司上班时间
						long companyEndTime = DateUtil.strDateToShortTime("17:30").getTime(); // 公司下班时间
						float companyNormalHours = DateUtil.getDifferenceHour(companyStartTime, companyEndTime).floatValue();
						if(firstClockTime <= companyStartTime){ // 没迟到
							if(lastClockTime >= companyEndTime){ // 没早退
								normalHours = companyNormalHours;
							}else if(lastClockTime > companyStartTime ){ // 早退
								// 最后打卡时间 - 上班时间
								normalHours = DateUtil.getDifferenceHour(companyStartTime, lastClockTime).floatValue();
							}else{
								normalHours = 0;
							}
						}else{ // 迟到
							if(lastClockTime >= companyEndTime && companyEndTime > firstClockTime){ // 没早退
								// 下班时间 - 最早打卡时间
								normalHours = DateUtil.getDifferenceHour(firstClockTime, companyEndTime).floatValue();
							}else{ // 早退
								// 最后打卡时间 - 最早打卡时间
								normalHours = DateUtil.getDifferenceHour(firstClockTime, lastClockTime).floatValue();
							}
						}
					}else { // 非标准、综合工时制 没有加班
						// 计算打卡时间差值
						normalHours = DateUtil.getDifferenceHour(firstClockTime, lastClockTime).floatValue();
					}
				}
				// 取此员工的加班时间
				DataGridModel model = new DataGridModel();
				model.setRows(0);
				model.getParams().put("emplId", emplid);
				model.getParams().put("status", Constant.APPLY_PASS);
				model.getParams().put("startTime", beforeTime);
				model.getParams().put("endTime", beforeTime);
				overtimeHours = getOverTime(model);
				
				dayReport.setNo(oaBillAttnDetail.getNo());
				dayReport.setBillDate(billDate);
				dayReport.setCreateTime(new Date());
				dayReport.setModifyTime(new Date());
				dayReport.setYear(DateUtil.getYear(billDate));
				dayReport.setMonth(DateUtil.getMonth(billDate));
				dayReport.setEmplId(emplid);
				dayReport.setEmplCode(oaBillAttnDetail.getEmplCode());
				dayReport.setEmplName(oaBillAttnDetail.getEmplName());
				dayReport.setManHoursTypeId(oaBillAttnDetail.getManHoursTypeId());
				dayReport.setManHoursTypeName(oaBillAttnDetail.getManHoursTypeName());
				dayReport.setNormalHours(normalHours);
				dayReport.setChangeNormalHours(normalHours);
				dayReport.setOvertimeHours(overtimeHours);
				dayReport.setChangeOvertimeHours(overtimeHours);
				dayReport.setAttnTypeId(oaBillAttnDetail.getAttnTypeId());
				dayReport.setAttnTypeName(oaBillAttnDetail.getAttnTypeName());
				dayReportService.create(dayReport);
			}
		}

	}
	// 获取员工加班时间
	private float getOverTime(DataGridModel param){
		BigDecimal overtimeHours = new BigDecimal(0f);
		List<OaBillOvertimeApplication> doListByCondition = overtimeManagerService.doListByCondition(param);
		for(OaBillOvertimeApplication o : doListByCondition){
			 overtimeHours.add(DateUtil.getDifferenceHour(o.getOffDutyTime().getTime(), o.getOnDutyTime().getTime()));
		}
		return overtimeHours.floatValue();
	}
		
		
		
	public static void main(String[] a){
		/*Date date = DateUtil.parseShotStringToDate("2017-8-1");
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		String string = calendar.getTime().toString();
		String beforeTime = DateUtil.dateToStrShort(calendar.getTime());
		long firstClockTime = DateUtil.strDateToShortTime(DateUtil.dateToShortTime(DateUtil.parseStringToDate("2017-08-27 08:30:00"))).getTime();
		long lastClockTime = DateUtil.strDateToShortTime(DateUtil.dateToShortTime(DateUtil.parseStringToDate("2017-08-27 20:30:00"))).getTime();
		BigDecimal b_diffTime = new BigDecimal(lastClockTime - firstClockTime);
		BigDecimal b_oneHours = new BigDecimal(60 * 60 *1000);
		BigDecimal diff = b_diffTime.divide(b_oneHours, 1, BigDecimal.ROUND_HALF_UP); // 保留一位小数四舍五入
		System.out.println(diff);*/
	}
	
	/**
	 * @Description: 月结表统计
	 * @author dongyibin
	 * @date 2017-8-19 下午8:37:47
	 */
	@Scheduled(cron="0 30 1 1 * ?") // 每月1号1点30分执行
	public void monthlyReport(){
		Calendar calendar = Calendar.getInstance();
		int year = calendar.get(Calendar.YEAR);
		int month = calendar.get(Calendar.MONTH); // 月份从0开始，此为上月月份
		calendar.set(Calendar.DAY_OF_MONTH, 0); // 取上月的最后一天
		Date billDate = calendar.getTime();
		String firstDayOfMonth = year + "-" + month + "-" + "01";
		String lastDayOfMonth = DateUtil.dateToStrShort(billDate);
		DataGridModel param = new DataGridModel();
		param.setRows(0);
		param.getParams().put("startTime", firstDayOfMonth + " 00:00:00");
		param.getParams().put("endTime", lastDayOfMonth + " 23:59:59");
		int monthReportId = 0;
		// 取这个月有日报数据的员工
		List<OaBillAttnDayReport> users = dayReportService.getDistinctByEmplid(param);
		for(OaBillAttnDayReport user : users){
			String emplId = user.getEmplId();
			if(StringUtils.isBlank(emplId)){
				continue;
			}else{
				OaBillAttnMonthReport monthReport = new OaBillAttnMonthReport();
				monthReport.setNo(System.currentTimeMillis()+"");
				monthReport.setStatus(Constant.STATUS_TRUE);
				monthReport.setBillDate(billDate);
				monthReport.setCreateTime(new Date());
				monthReport.setModifyTime(new Date());
				monthReport.setYear(year);
				monthReport.setMonth(month);
				monthReport.setEmplId(emplId);
				monthReport.setEmplCode(user.getEmplCode());
				monthReport.setEmplName(user.getEmplName());
				monthReport.setManHoursTypeId(user.getManHoursTypeId());
				monthReport.setManHoursTypeName(user.getManHoursTypeName());
				int tag = monthReportService.create(monthReport);
				// 获取此月报id
				if(tag > 0){
					DataGridModel reportParam = new DataGridModel();
					reportParam.setRows(0);
					reportParam.getParams().put("emplId", emplId);
					reportParam.getParams().put("year", year);
					reportParam.getParams().put("month", month);
					reportParam.getSortBy().add(new DataGridSortModel("modify_time", DataGridSortModel.DESC));
					monthReportId = monthReportService.doListByCondition(reportParam).get(0).getId();
				}else{
					monthReportId = 0;
					logger.error("保存月报失败，用户：" + emplId);
				}
			}
			
			if(monthReportId > 0){
				param.getParams().put("emplId", emplId);
				param.getSortBy().add(new DataGridSortModel("create_time", DataGridSortModel.ASC));
				int attendanceDay = 0; // 出勤天数
				BigDecimal attendanceHours = new BigDecimal(0f); // 出勤小时数
				// 取此员工这个月的日结数据
				List<OaBillAttnDayReport> dayReports = dayReportService.doListByCondition(param);
				// 出勤天数
				if(dayReports != null){
					attendanceDay = dayReports.size();
				}
				saveMonthReportDtl(monthReportId, Constant.MONTHREPORT_ATTENDANCE_DAYS, attendanceDay);
				
				for(OaBillAttnDayReport dayReport : dayReports){
					attendanceHours = attendanceHours.add(new BigDecimal(dayReport.getNormalHours()));
				}
				// 出勤小时数
				saveMonthReportDtl(monthReportId, Constant.MONTHREPORT_ATTENDANCE_HOURS, attendanceHours.floatValue());
				
				// 加班时长
				param.getParams().put("status", Constant.APPLY_PASS);
				param.getSortBy().clear();
				saveMonthReportDtl(monthReportId, Constant.MONTHREPORT_OVERTIME_HOURS, getOverTime(param));
				
				// 法定节假日加班时长
				param.getParams().put("isHolidays", Constant.STATUS_TRUE);
				saveMonthReportDtl(monthReportId, Constant.MONTHREPORT_HOLIDAYOVERTIME_HOURS, getOverTime(param));
				
				// 获取员工次月分请假申请
				DataGridModel leaveParam = new DataGridModel();
				leaveParam.setRows(0);
				leaveParam.getParams().put("emplId", emplId);
				leaveParam.getParams().put("leaveBeginTime", firstDayOfMonth + " 00:00:00");
				leaveParam.getParams().put("leaveEndTime", lastDayOfMonth + " 23:59:59");
				leaveParam.getParams().put("status", Constant.APPLY_PASS);
				leaveParam.getSortBy().add(new DataGridSortModel("bill_date", DataGridSortModel.ASC));
				List<OaBillLeaveApplication> leaveApplications = leaveManagerService.doListByCondition(leaveParam);
				BigDecimal leaveHours = new BigDecimal(0f); // 总请假时长
				// 解析请假类型
				Map<String, BigDecimal> m = new HashMap<>();
				for(OaBillLeaveApplication leave : leaveApplications){
					String key = leaveTypeManagerService.get(leave.getLeaveTypeId()).getCode();
					BigDecimal duration = DateUtil.getDifferenceHour(leave.getLeaveBeginTime().getTime(), leave.getLeaveEndTime().getTime());
					if(m.get(key) == null){
						m.put(key, duration);
					}else{
						m.put(key, m.get(key).add(duration));
					}
					leaveHours = leaveHours.add(duration);
				}
				saveMonthReportDtl(monthReportId, Constant.MONTHREPORT_LEAVE_HOURS, leaveHours.floatValue());
				for(String key : m.keySet()){
					saveMonthReportDtl(monthReportId, key, m.get(key).floatValue());
				}
			}
		}
	}
	
	/**
	 * @Description: 保存月报计算数据 
	 * @param monthReportId
	 * @param reportKey
	 * @param reportValue
	 * @author dongyibin
	 * @date 2017-9-3 下午4:46:02
	 */
	private void saveMonthReportDtl(int monthReportId, String reportKey, float reportValue){
		OaBillAttnMonthReportDtl monthReportDtl = new OaBillAttnMonthReportDtl();
		monthReportDtl.setBillId(monthReportId);
		monthReportDtl.setReportKey(reportKey);
		monthReportDtl.setReportVal(reportValue);
		monthReportDtlService.create(monthReportDtl);
	}
}
